package com.cardone.context;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.web.context.request.*;

import javax.servlet.http.HttpServletRequest;

/**
 * 上下文支持
 *
 * @author yaohaitao
 */
@Slf4j
public class ContextHolder implements ApplicationContextAware {
    /**
     * Spring ApplicationContext
     */
    @Getter
    private static ApplicationContext applicationContext;
    /**
     * 登录用户键
     */
    private static ThreadLocal<String> loginKey = new ThreadLocal<>();
    /**
     * 站点标识
     */
    private static ThreadLocal<String> siteId = new ThreadLocal<>();
    /**
     * parameters
     */
    private static ThreadLocal<String> parameters = new ThreadLocal<>();
    /**
     * 当前key
     */
    private static ThreadLocal<String> determineCurrentLookupKey = new ThreadLocal<>();
    /**
     * 超级角色标识
     */
    private static ThreadLocal<String> superRoleId = new ThreadLocal<>();
    /**
     * 组标识
     */
    private static ThreadLocal<String> groupId = new ThreadLocal<>();
    /**
     * 默认主页视图
     */
    @Setter
    @Getter
    private static String defaultServletPath = "/index.html";

    public static String getDetermineCurrentLookupKey() {
        return determineCurrentLookupKey.get();
    }

    public static void setDetermineCurrentLookupKey(String determineCurrentLookupKey) {
        ContextHolder.determineCurrentLookupKey.set(determineCurrentLookupKey);
    }

    public static String getLoginKey() {
        return com.cardone.context.ContextHolder.loginKey.get();
    }

    public static void setLoginKey(String loginKey) {
        if (org.apache.commons.lang3.StringUtils.isBlank(loginKey)) {
            com.cardone.context.ContextHolder.loginKey.remove();
        } else {
            com.cardone.context.ContextHolder.loginKey.set(loginKey);
        }
    }

    /**
     * 获取request
     *
     * @return request
     */
    public static String getServletPath() {
        return getServletPath(getRequest());
    }

    /**
     * 获取request
     *
     * @return request
     */
    public static String getServletPath(HttpServletRequest request) {
        String servletPath = request.getServletPath();

        return StringUtils.defaultIfBlank(servletPath, defaultServletPath);
    }

    /**
     * 获取request
     *
     * @return request
     */
    public static HttpServletRequest getRequest() {
        final RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

        if (requestAttributes == null) {
            return null;
        }

        final HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();

        return request;
    }

    public static String getSiteId() {
        return com.cardone.context.ContextHolder.siteId.get();
    }

    public static void setSiteId(String siteId) {
        if (org.apache.commons.lang3.StringUtils.isBlank(siteId)) {
            com.cardone.context.ContextHolder.siteId.remove();
        } else {
            com.cardone.context.ContextHolder.siteId.set(siteId);
        }
    }

    public static String getParameters() {
        return com.cardone.context.ContextHolder.parameters.get();
    }

    public static void setParameters(String parameters) {
        com.cardone.context.ContextHolder.parameters.set(parameters);
    }

    public static String getSuperRoleId() {
        return com.cardone.context.ContextHolder.superRoleId.get();
    }

    public static void setSuperRoleId(String superRoleId) {
        if (org.apache.commons.lang3.StringUtils.isBlank(superRoleId)) {
            com.cardone.context.ContextHolder.superRoleId.remove();
        } else {
            com.cardone.context.ContextHolder.superRoleId.set(superRoleId);
        }
    }

    public static String getGroupId() {
        return com.cardone.context.ContextHolder.groupId.get();
    }

    public static void setGroupId(String groupId) {
        if (org.apache.commons.lang3.StringUtils.isBlank(groupId)) {
            com.cardone.context.ContextHolder.groupId.remove();
        } else {
            com.cardone.context.ContextHolder.groupId.set(groupId);
        }
    }

    /**
     * 获取 bean
     *
     * @param requiredType 类型
     * @return bean
     */
    public static <T> T getBean(final Class<T> requiredType) {
        return ContextHolder.getBean(requiredType, requiredType.getName());
    }

    /**
     * 获取 bean
     *
     * @param name         名称
     * @param requiredType 类型
     * @return bean
     */
    public static <T> T getBean(final Class<T> requiredType, final String name) {
        if (ContextHolder.applicationContext == null) {
            return null;
        }

        if (ContextHolder.applicationContext.containsBean(name)) {
            return ContextHolder.applicationContext.getBean(name, requiredType);
        }

        final String[] beanNames = ContextHolder.applicationContext.getBeanNamesForType(requiredType);

        if (ArrayUtils.isEmpty(beanNames)) {
            ContextHolder.log.error("未配置spring bean:" + requiredType.getName());

            return null;
        }

        if (ArrayUtils.getLength(beanNames) > 1) {
            throw new DictionaryException("配置的spring bean过多:" + org.apache.commons.lang3.StringUtils.join(beanNames));
        }

        return ContextHolder.applicationContext.getBean(beanNames[0], requiredType);
    }

    /**
     * 获取 bean
     *
     * @param name 名称
     * @return bean
     */
    public static Object getBean(final String name) {
        if (ContextHolder.applicationContext == null) {
            return null;
        }

        return ContextHolder.applicationContext.getBean(name);
    }

    public static void initApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ContextHolder.applicationContext = applicationContext;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ContextHolder.initApplicationContext(applicationContext);
    }
}
